package dd.lo.chapter10;

import dd.lo.util.ImageUtils;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.ByteArrayInputStream;

/**
 * Exercise 2
 * Create a 100 × 100 single-channel image. Set all pixels to 0. Finally, set the center pixel equal to 255.
 * Smooth this image with a 5 × 5 Gaussian filter and display the results. What did you find?
 * Do this again but with a 9 × 9 Gaussian filter.
 * What does it look like if you start over and smooth the image twice with the 5 × 5 filter? Compare this with the 9 × 9 results. Are they nearly the same? Why or why not?
 */
public class Exercise2 extends Application {

    private enum Mode {
        A,
        B,
        C,
        D, //origin image
        ;
    }

    private static final int DEFAULT_WIDTH = 1080;
    private static final int DEFAULT_HEIGHT = 768;

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        launch(args);
    }

    private ImageView imageView;

    private Mat srcImg;

    private int modeIdx = 0;

    private Mode mode = Mode.A;

    private int iteration = 1;

    private void gaussianBlur(Mat srcImg) {
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                Mat dst = Mat.zeros(srcImg.size(), CvType.CV_8U);
                if (mode == Mode.A) {
                    //剩下很模糊的点
                    Imgproc.GaussianBlur(srcImg, dst, new Size(5, 5), 0.0);
                } else if (mode == Mode.B) {
                    //基本上看不到，图片几乎全黑
                    Imgproc.GaussianBlur(srcImg, dst, new Size(9, 9), 0.0);
                } else if (mode == Mode.C) {
                    //几乎和B的情况一样，相当于涂抹了2次，被周围黑的影响太大了
                    Imgproc.GaussianBlur(srcImg, dst, new Size(5, 5), 0.0);
                    Imgproc.GaussianBlur(dst, dst, new Size(5, 5), 0.0);
                } else {
                    srcImg.copyTo(dst);
                }
                //调整图片大小以用于展示
                ImageUtils.fitImgSize(dst, DEFAULT_WIDTH, DEFAULT_HEIGHT);
                MatOfByte buffer = new MatOfByte();
                Imgcodecs.imencode(".jpeg", dst, buffer);
                Platform.runLater(() -> imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray()))));
                return null;
            }
        };
        new Thread(task).start();
    }

    @Override
    public void start(Stage stage) {
        //File chooser
        Button imageChooser = new Button("选择图片");
        imageChooser.setOnMouseClicked(e -> {
            //生成一张图片
            srcImg = new Mat(new Size(100, 100), CvType.CV_8UC3);
            srcImg.setTo(new Scalar(0, 0, 0));
            srcImg.put(50, 50, 255, 255, 255);
            gaussianBlur(srcImg);
        });
        //Mode indicator
        Text modeText = new Text("当前模式：" + mode);
        Button prevModeButton = new Button("上一个模式");
        prevModeButton.setOnMouseClicked(e -> {
            --modeIdx;
            modeIdx = (Mode.values().length + modeIdx) % Mode.values().length;
            mode = Mode.values()[modeIdx];
            modeText.setText("当前模式：" + mode);
            gaussianBlur(srcImg);
        });
        Button nextModeButton = new Button("下一个模式");
        nextModeButton.setOnMouseClicked(e -> {
            ++modeIdx;
            modeIdx = modeIdx % Mode.values().length;
            mode = Mode.values()[modeIdx];
            modeText.setText("当前模式：" + mode);
            gaussianBlur(srcImg);
        });
        FlowPane bottomControl = new FlowPane();
        bottomControl.getChildren().addAll(imageChooser, prevModeButton, modeText, nextModeButton);
        bottomControl.setPrefHeight(50);
        BorderPane root = new BorderPane();
        imageView = new ImageView();
        root.setCenter(imageView);
        root.setBottom(bottomControl);
        Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT + 50);
        stage.setScene(scene);
        stage.setTitle("Exercise2-Gaussian blur comparison");
        stage.setResizable(false);
        stage.show();
    }
}
